using NetduinoRobot.Common;
using System;
using System.Reflection;
using System.Text;

namespace NetduinoHappyHour.Util
{
    /// <summary>
    /// Collects all classes in assembly of type IExecutable
    /// Written by: Salvador Richter
    /// Appache License Version 2.0 
    /// </summary>
    public class ExecutableCommands : IExecutable, IInteractionResponseMessage
    {
        private string _message;

        public ExecutableCommands() { }

        public void Execute()
        {
            _message = GetExecutables();
        }

        public string ResponseMessage()
        {
            return _message;
        }

        /// <summary>
        /// Collects all classes in assembly of type IExecutable
        /// </summary>
        /// <seealso cref="NetduinoRobot.Common.CommandHelper.CommandSeparator"/>
        /// <returns>string containing classnames of classes of type IExecutable, classnames were separated by CommandSeparator</returns>
        public string GetExecutables()
        {
            StringBuilder sBuilder = new StringBuilder();
            Assembly a = Assembly.GetExecutingAssembly();
            Type[] types = a.GetTypes();
            foreach (Type type in types)
            {
                if (!type.IsInterface && !type.IsAbstract)
                {
                    Type[] interfaceTypes = type.GetInterfaces();
                    foreach (Type interfaceType in interfaceTypes)
                    {
                        if (interfaceType.Equals(typeof(IExecutable)))
                        {
                            
                            // add more information, like all constructors
                            // TODO replace hack by valid reflection if available
                            // added request at https://netmf.codeplex.com/workitem/2320 for GetConstructors
                            //if (type.BaseType.Equals(typeof(MyConstructors)))
                            if (type.GetMethod("GetConstructors")!=null)
                            {
                                ConstructorInfo info = type.GetConstructor(new Type[0]);
                                IConstructors myCons = (IConstructors)info.Invoke(null);
                                foreach (String s in myCons.GetConstructors())
                                {
                                    sBuilder.Append(type.Name);
                                    sBuilder.Append(s);
                                    sBuilder.Append(CommandHelper.CommandSeparator);
                                }
                            }
                            else
                            {
                                sBuilder.Append(type.Name);
                                sBuilder.Append(CommandHelper.CommandSeparator);
                            }
                        }
                    }
                }
            }
            return sBuilder.ToString();
        }
    }
}
